
/* some code *stolen* from the great book generative gestaltung
 * http://www.generative-gestaltung.de
 */

package wikiPhilia_two;

import generativedesign.GenerativeDesign;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;

import processing.core.PApplet;
import processing.xml.XMLElement;

public class WArticle {
	protected static String QUERY_CAT_IN = "http://en.wikipedia.org/w/api.php?format=xml&action=query&prop=categories&titles=";
	protected static String QUERY_CAT_OUT = "&cllimit=500&redirects&clshow=!hidden"; //"&clnamespace=0" taken out
	protected static String QUERY_CAT_CONTINUE = "&clcontinue=";
	protected static String QUERY_CATMEM_IN ="http://en.wikipedia.org/w/api.php?format=xml&action=query&list=categorymembers&cmtype=page|subcat&cmprop=type|title&cmtitle=";  
	protected static String QUERY_CATMEM_OUT = "&cmlimit=500&redirects";
	protected static String QUERY_CATMEM_CONTINUE = "&cmcontinue=";
	protected static String QUERY_LINKS_IN ="http://en.wikipedia.org/w/api.php?format=xml&action=query&titles=";  
	protected static String QUERY_LINKS_OUT = "&prop=links&pllimit=500&plnamespace=0";
	protected static String QUERY_LINKS_CONTINUE = "&plcontinue=";
	protected static String QUERY_BACKLINKS_IN ="http://en.wikipedia.org/w/api.php?format=xml&action=query&bltitle=";  
	protected static String QUERY_BACKLINKS_OUT = "&list=backlinks&bllimit=500&blnamespace=0";
	protected static String QUERY_BACKLINKS_CONTINUE = "&blcontinue=";
	protected String title;
	private boolean isAPerson;
	protected float mass;
	protected PApplet parent;
	protected XMLElement[] children; 
    protected int myYob; 
    protected int myYod; 

 

	//TODO: private int yob, yod; //year of birth, year of death
	//TODO: implement asynchronous loading (as seen in generative gestaltung, or with Pierre)
	
	public WArticle(PApplet theParent, String theTitle) {
		parent = theParent;
		title = theTitle;
		//isAPerson = isItAPerson();
	}
	
	public void initPerson() {
		isAPerson = isItAPerson();
	}
		
	private boolean isItAPerson() {
		boolean answer = false;
		String url = encodeURL(QUERY_CAT_IN+title+QUERY_CAT_OUT);
	    //XMLElement linksXML = GenerativeDesign.loadXMLAsync(parent, url);
		XMLElement linksXML = new XMLElement(parent, url);
	    ArrayList categories = new ArrayList();
	    if (linksXML.hasChildren()) {
	        // get titles of categories
	        children = linksXML.getChildren("query/pages/page/categories/cl");
	        for (int i = 0; i < children.length; i++) {
	          String title = children[i].getStringAttribute("title");
	         
	          if (title.contains("births")){
	        	  answer = true; 
	    	      String[] b = parent.splitTokens(title, " :");
	    	      
	    	      try {
	    	    	  myYob = Integer.parseInt(b[1]);
				} catch (Exception e) {
					// TODO: handle exception
					System.out.println(title + " contains no valid year of birth!");
				} 
	    	 	  
	          }
	          
	          if (title.contains("deaths")){
	        	  answer = true; 
	        	  //myyod = title; 
	        	  String[] d = parent.splitTokens(title, " :");
	        	  try {
	        		  myYod = Integer.parseInt(d[1]);
				} catch (Exception e) {
					// TODO: handle exception
					System.out.println(title + " contains no valid year of death!");
				} 
	        	  
	        	
	        	 
	          }

	          categories.add(title);
	        }
	    }
	    //get an Iterator object for ArrayList using iterator() method.
	 
	   /*
	    Iterator itr = categories.iterator();
	 
	    //use hasNext() and next() methods of Iterator to iterate through the elements
	    while(itr.hasNext()) {
	    	String s = itr.next().toString();
	    	//System.out.println(s);
	    	if (s.contains("deaths") || s.contains("births")) {
	    		answer = true;
	    		return answer;
	    	}
	    }*/
	    // yobyod(); 
    	return answer; 
	}
	
	
	public String toString() {
		return title;
	}
	
	

	  public int yob() {
		  return myYob; 

	}	
	  

	  public int yod() {
		return myYod; 
	}	
	
	  
	/* public int[] yobyo(){
	 
		 if (checkPerson() == true){
			 
			 
		 }
	return years[0,1]
	 
	 }*/
	  
	//public Sti
	
	public boolean checkPerson() {
		return isItAPerson();
	}
	 
	
	
	ArrayList<WCategory> getCategories() {
		ArrayList<WCategory> result = new ArrayList<WCategory>();
		String continueFromTitle = null;
		String url = encodeURL(QUERY_CAT_IN+title+QUERY_CAT_OUT);
	    //XMLElement linksXML = GenerativeDesign.loadXMLAsync(parent, url);
		XMLElement linksXML = new XMLElement(parent, url);
	    if (linksXML.hasChildren()) {
	        // get titles of categories
	        XMLElement[] children = linksXML.getChildren("query/pages/page/categories/cl");
	        int nr = children.length; //xmlObj.getChildCount(); 
	        System.out.println("SuperCategories count: " + nr); 
	        for (int i = 0; i < children.length; i++) {
	          String title = children[i].getStringAttribute("title");
	          //if (title.startsWith("Category:")) title = title.substring(9);
	          result.add(new WCategory(parent,title));
	        }
	    }
	    
		while(continueFromTitle != null) {
		    // get titles of categories
			url = encodeURL(QUERY_CAT_IN+title+QUERY_CAT_CONTINUE+continueFromTitle+QUERY_CAT_OUT);
			linksXML = new XMLElement(parent, url);
	        XMLElement[] children = linksXML.getChildren("query/pages/page/categories/cl");
	        int nr = children.length; //xmlObj.getChildCount(); 
	        System.out.println("SuperCategories count: " + nr); 
	        for (int i = 0; i < children.length; i++) {
	          //if (title.startsWith("Category:")) title = title.substring(9);
	          String title = children[i].getStringAttribute("title");
	          //if (title.startsWith("Category:")) title = title.substring(9);
	          result.add(new WCategory(parent,title));
	        }
			if (linksXML.getChild("query-continue") != null) {
				continueFromTitle = linksXML.getChild("query-continue/categories").getStringAttribute("clcontinue");
				System.out.println(continueFromTitle);
			} else {
				continueFromTitle = null;
			}
		}
	    
	    
	    return result;    
	}

	ArrayList<String> getCategoryTitles() {
		ArrayList<String> result = new ArrayList<String>();
		String continueFromTitle = null;
		String url = encodeURL(QUERY_CAT_IN+title+QUERY_CAT_OUT);
	    //XMLElement linksXML = GenerativeDesign.loadXMLAsync(parent, url);
		XMLElement linksXML = new XMLElement(parent, url);
	    if (linksXML.hasChildren()) {
	        // get titles of categories
	        XMLElement[] children = linksXML.getChildren("query/pages/page/categories/cl");
	        int nr = children.length; //xmlObj.getChildCount(); 
	        System.out.println("SuperCategories count: " + nr); 
	        for (int i = 0; i < children.length; i++) {
	          String title = children[i].getStringAttribute("title");
	          //if (title.startsWith("Category:")) title = title.substring(9);
	          result.add(title);
	        }
			if (linksXML.getChild("query-continue") != null) {
				continueFromTitle = linksXML.getChild("query-continue/categories").getStringAttribute("clcontinue");
				System.out.println(continueFromTitle);
			}
	    }
		while(continueFromTitle != null) {
		    // get titles of categories
			url = encodeURL(QUERY_CAT_IN+title+QUERY_CAT_CONTINUE+continueFromTitle+QUERY_CAT_OUT);
			linksXML = new XMLElement(parent, url);
	        XMLElement[] children = linksXML.getChildren("query/pages/page/categories/cl");
	        int nr = children.length; //xmlObj.getChildCount(); 
	        System.out.println("SuperCategories count: " + nr); 
	        for (int i = 0; i < children.length; i++) {
	          String title = children[i].getStringAttribute("title");
	          //if (title.startsWith("Category:")) title = title.substring(9);
	          result.add(title);
	        }
			if (linksXML.getChild("query-continue") != null) {
				continueFromTitle = linksXML.getChild("query-continue/categories").getStringAttribute("plcontinue");
				System.out.println(continueFromTitle);
			} else {
				continueFromTitle = null;
			}
	    
		
		
		}
	    
	    return result;    
	}
	
	ArrayList<WArticle> getLinks() {
		ArrayList<WArticle> result = new ArrayList<WArticle>();
		String continueFromTitle = null;
		String url = encodeURL(QUERY_LINKS_IN+title+QUERY_LINKS_OUT);
		//XMLElement linksXML = GenerativeDesign.loadXMLAsync(parent, url);
		XMLElement linksXML = new XMLElement(parent, url);
		if (linksXML.hasChildren()) {
			// get titles of categories
			XMLElement[] children = linksXML.getChildren("query/pages/page/links/pl");
	        int nr = children.length; //xmlObj.getChildCount(); 
	        System.out.println("Links count: " + nr); 
			for (int i = 0; i < children.length; i++) {
				String title = children[i].getStringAttribute("title");
				//if (title.startsWith("Category:")) title = title.substring(9);
				result.add(new WArticle(parent,title));
			}
			if (linksXML.getChild("query-continue") != null) {
				continueFromTitle = linksXML.getChild("query-continue/links").getStringAttribute("plcontinue");
				System.out.println(continueFromTitle);
			}
		}
		
		while(continueFromTitle != null) {
			url = encodeURL(QUERY_LINKS_IN+title+QUERY_LINKS_CONTINUE+continueFromTitle+QUERY_LINKS_OUT);
			//XMLElement linksXML = GenerativeDesign.loadXMLAsync(parent, url);
			linksXML = new XMLElement(parent, url);
			if (linksXML.hasChildren()) {
				// get titles of categories
				XMLElement[] children = linksXML.getChildren("query/pages/page/links/pl");
		        int nr = children.length; //xmlObj.getChildCount(); 
		        System.out.println("Links count: " + nr); 
				for (int i = 0; i < children.length; i++) {
					String title = children[i].getStringAttribute("title");
					//if (title.startsWith("Category:")) title = title.substring(9);
					result.add(new WArticle(parent,title));
				}
				if (linksXML.getChild("query-continue") != null) {
					continueFromTitle = linksXML.getChild("query-continue/links").getStringAttribute("plcontinue");
					System.out.println(continueFromTitle);
				} else {
					continueFromTitle = null;
				}
			}
		
		}
		return result;    
	}
	
	ArrayList<String> getLinkTitles() {
		ArrayList<String> result = new ArrayList<String>();
		String url = encodeURL(QUERY_LINKS_IN+title+QUERY_LINKS_OUT);
		String continueFromTitle = null;
		XMLElement linksXML = new XMLElement(parent, url);
		if (linksXML.hasChildren()) {
			// get titles of categories
			XMLElement[] children = linksXML.getChildren("query/pages/page/links/pl");
	        int nr = children.length; //xmlObj.getChildCount(); 
	        System.out.println("Links count: " + nr); 
			for (int i = 0; i < children.length; i++) {
				String title = children[i].getStringAttribute("title");
				//if (title.startsWith("Category:")) title = title.substring(9);
				result.add(title);
			}
			if (linksXML.getChild("query-continue") != null) {
				continueFromTitle = linksXML.getChild("query-continue/links").getStringAttribute("plcontinue");
				System.out.println(continueFromTitle);
			}
		}
		while(continueFromTitle != null) {
			url = encodeURL(QUERY_LINKS_IN+title+QUERY_LINKS_CONTINUE+continueFromTitle+QUERY_LINKS_OUT);
			//XMLElement linksXML = GenerativeDesign.loadXMLAsync(parent, url);
			linksXML = new XMLElement(parent, url);
			if (linksXML.hasChildren()) {
				// get titles of categories
				XMLElement[] children = linksXML.getChildren("query/pages/page/links/pl");
		        int nr = children.length; //xmlObj.getChildCount(); 
		        System.out.println("Links count: " + nr); 
				for (int i = 0; i < children.length; i++) {
					String title = children[i].getStringAttribute("title");
					//if (title.startsWith("Category:")) title = title.substring(9);
					result.add(title);
				}
				if (linksXML.getChild("query-continue") != null) {
					continueFromTitle = linksXML.getChild("query-continue/links").getStringAttribute("plcontinue");
					System.out.println(continueFromTitle);
				} else {
					continueFromTitle = null;
				}
			}
		
		}
		return result;    
	}
	
	ArrayList<WArticle> getBackLinks() {
		ArrayList<WArticle> result = new ArrayList<WArticle>();
		String continueFromTitle = null;
		String url = encodeURL(QUERY_BACKLINKS_IN+title+QUERY_BACKLINKS_OUT);
		//XMLElement linksXML = GenerativeDesign.loadXMLAsync(parent, url);
		XMLElement linksXML = new XMLElement(parent, url);
		if (linksXML.hasChildren()) {
			// get titles of categories
			XMLElement[] children = linksXML.getChildren("query/backlinks/bl");
			int nr = children.length; //xmlObj.getChildCount(); 
			System.out.println("BackLinks count: " + nr); 
			for (int i = 0; i < children.length; i++) {
				String title = children[i].getStringAttribute("title");
				//if (title.startsWith("Category:")) title = title.substring(9);
				result.add(new WArticle(parent,title));
			}
			if (linksXML.getChild("query-continue") != null) {
				continueFromTitle = linksXML.getChild("query-continue/backlinks").getStringAttribute("blcontinue");
				System.out.println(continueFromTitle);
			}
		}
		
		while(continueFromTitle != null) {
			url = encodeURL(QUERY_BACKLINKS_IN+title+QUERY_BACKLINKS_CONTINUE+continueFromTitle+QUERY_BACKLINKS_OUT);
			//XMLElement linksXML = GenerativeDesign.loadXMLAsync(parent, url);
			linksXML = new XMLElement(parent, url);
			if (linksXML.hasChildren()) {
				// get titles of categories
				XMLElement[] children = linksXML.getChildren("query/backlinks/bl");
		        int nr = children.length; //xmlObj.getChildCount(); 
		        System.out.println("BackLinks count: " + nr); 
				for (int i = 0; i < children.length; i++) {
					String title = children[i].getStringAttribute("title");
					//if (title.startsWith("Category:")) title = title.substring(9);
					result.add(new WArticle(parent,title));
				}
				if (linksXML.getChild("query-continue") != null) {
					continueFromTitle = linksXML.getChild("query-continue/backlinks").getStringAttribute("blcontinue");
					System.out.println(continueFromTitle);
				} else {
					continueFromTitle = null;
				}
			}
		
		}

		
		return result;    
	}
	
	
	
	// function encodeURL based on a post on the processing discourse pages
	// posted by PhiLho on May 28th, 2008
	//
	// converts special chars in a string to be suitable for a url
	public String encodeURL(String url) {

	  // Use URI to encode low Ascii characters depending on context of various parts
	  // For some reason, uri = new URI(url) chokes on space, so we have to split the URL
	  String scheme = null;  // http, ftp, etc.
	  String ssp = null; // scheme-specific part
	  String fragment = null; // #anchor for example
	  int colonPos = url.indexOf(":");
	  if (colonPos < 0) return "Not an URL";
	  scheme = url.substring(0, colonPos);
	  ssp = url.substring(colonPos + 1);
	  int fragPos = ssp.lastIndexOf("#");
	  if (fragPos >= 0) {
	    // Won't work if there is no real anchor/fragment
	    // but this char is part of one parameter of the query,
	    // but it is a bit unlikely...
	    // That's probably why Java doesn't want to do it automatically,
	    // it must be disambiguated manually
	    fragment = ssp.substring(fragPos + 1);
	    ssp = ssp.substring(0, fragPos);
	  }

	  URI uri = null;
	  try {
	    uri = new URI(scheme, ssp, fragment);
	  } 
	  catch (URISyntaxException use) { 
	    return use.toString(); 
	  }
	  String encodedURL1 = null;
	  try {
	    encodedURL1 = uri.toURL().toString();
	  } 
	  catch (MalformedURLException mue) { 
	    return mue.toString(); 
	  }
	  // Here, we still have Unicode chars unchanged

	  byte[] utf8 = null;
	  // Convert whole string to UTF-8 at once: low Ascii (below 0x80) is unchanged, other stuff is converted
	  // to UTF-8, which always have the high bit set.
	  try {
	    utf8 = encodedURL1.getBytes("UTF-8");
	  } 
	  catch (UnsupportedEncodingException uee) { 
	    return uee.toString(); 
	  }

	  StringBuffer encodedURL = new StringBuffer();

	  byte[] conv = new byte[1];
	  for (int i = 0; i < utf8.length; i++) {
	    // Beyond Ascii: high bit is set, hence negative byte
	    if (utf8[i] < 0) {
	      encodedURL.append("%" + Integer.toString(256 + (int)utf8[i], 16));
	    }
	    else {
	      conv[0] = utf8[i];
	      try {
	        encodedURL.append(new String(conv, "ASCII")); // Convert back to Ascii
	      } 
	      catch (UnsupportedEncodingException uee) { 
	        return uee.toString(); 
	      }
	    }
	  }

	  return encodedURL.toString();
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public static String getQUERY_CATMEM_IN() {
		return QUERY_CATMEM_IN;
	}

	public static void setQUERY_CATMEM_IN(String qUERY_CATMEM_IN) {
		QUERY_CATMEM_IN = qUERY_CATMEM_IN;
	}

	public int getMyyob() {
		return myYob;
	}

	public void setMyyob(int myyob) {
		this.myYob = myyob;
	}

	public int getMyyod() {
		return myYod;
	}

	public void setMyyod(int myyod) {
		this.myYod = myyod;
	}

	
}
